/*
 * @(#)DocumentRetrievalManager.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.calendar.core;

import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dcivision.alert.core.AlertManager;
import com.dcivision.alert.core.NotificationAdapter;
import com.dcivision.calendar.bean.CalendarPerference;
import com.dcivision.calendar.bean.CalendarRecord;
import com.dcivision.calendar.bean.CalendarRecur;
import com.dcivision.calendar.dao.CalendarPerferenceDAObject;
import com.dcivision.calendar.dao.CalendarRecordDAObject;
import com.dcivision.calendar.dao.CalendarRecurDAObject;
import com.dcivision.calendar.web.MaintCalendarRecordForm;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.UserInfoFactory;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.GenericAddress;
import com.dcivision.framework.notification.EmailDeliveryMessage;
import com.dcivision.framework.notification.NotificationWay;
import com.dcivision.framework.notification.NotificationWayFactory;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractSearchForm;
import com.dcivision.user.dao.MtmUserRecordUserGroupDAObject;
import com.dcivision.user.dao.MtmUserRecordUserRoleDAObject;
import com.dcivision.user.dao.UserRecordDAObject;


/**
 * <p>Class Name:       CalendarRetrievalManager.java    </p>
 * <p>Description:      The class mainly handle the schedule list process and retrieval operations.</p>
 * @author              Jim Zhou
 * @company             DCIVision Limited
 * @creation date       08/24/2006
 * @version             $Revision: 1.4.2.3 $
 */

public class CalendarRetrievalManager {

  protected Log log = LogFactory.getLog(this.getClass().getName());
  private SessionContainer sessionContainer;
  private Connection conn;
  
  public CalendarRetrievalManager(SessionContainer sessionContainer, Connection conn){
  	this.sessionContainer = sessionContainer;
  	this.conn = conn;
  }  
  
  public synchronized void release() {
    this.sessionContainer = null;
    this.conn = null;
  }

  public ArrayList getSortedList( 
      AbstractSearchForm form,
      HttpServletRequest request, 
      String navMode,
      int selectedUserID, 
      Integer staffID,
      Timestamp startDate, 
      Timestamp endDate)
  		throws ApplicationException {
  	ArrayList sortedList = new ArrayList();
    ArrayList calendarList = null;
    CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(sessionContainer, conn);
    int selectedGroupID = this.getSelectedGroupID(request);

    try {
	  	//add normal event/meeting
	    if (selectedUserID == sessionContainer.getUserRecordID().intValue()
	        || selectedUserID == -1) {
		    if (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT) || selectedUserID == sessionContainer.getUserRecordID().intValue()){
		      calendarList=this.getCalenarList(sessionContainer, conn, form,
		                                         startDate, endDate, selectedUserID);
			    ArrayList calendarLists = null;
			    if (!Utility.isEmpty(calendarList)) {
			      sortedList.addAll(calendarList);
			      calendarLists = (ArrayList)this.createVirtualRecordForRecurring(sessionContainer,conn,calendarList,startDate,endDate,navMode,"R");
			    }
			    if (!Utility.isEmpty(calendarLists)) {
			    	sortedList.addAll(calendarLists);
			    }
	    	}
	    }
	  	
	  	//add shared event/meeting
	    if (selectedUserID != sessionContainer.getUserRecordID().intValue()){
		    if (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT)){
		    	ArrayList sharedList = (ArrayList)calendarRecordDAO.getSharedCalendarListByOthersGroupsAndRoles(
		    			form,
		    			sessionContainer.getUserRecordID(),
		    			new Integer(selectedUserID),
		    			new Integer(selectedGroupID),
		    			null,
		    			startDate,
		    			endDate,
							new String[] {
									CalendarRecord.EVENT_TYPE_CALENDAR_MEETING,
									CalendarRecord.EVENT_TYPE_CALENDAR_EVENT });
		    	ArrayList sharedLists = null;
		    	if (!Utility.isEmpty(sharedList)){
		      	sortedList.addAll(sharedList);
		      	sharedLists = (ArrayList)this.createVirtualRecordForRecurring(sessionContainer,conn,sharedList,startDate,endDate,navMode,"R");
		    	}
					if (!Utility.isEmpty(sharedLists)){
						sortedList.addAll(sharedLists);
					}
		    }
	    }
	  	
	  	//add accepted invitation meeting
	    if (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT)){
		    if (selectedUserID == sessionContainer.getUserRecordID().intValue()
		        || selectedUserID == -1) {
			    ArrayList acceptedList = (ArrayList)calendarRecordDAO.getInviteCalendarListByUserID(
			    		sessionContainer.getUserRecordID(),
			    		new Integer(-1),
			    		startDate,
			    		endDate,
							new String[] {
									CalendarRecord.EVENT_TYPE_CALENDAR_MEETING},
							"Y");
			    ArrayList acceptedLists = null;
			    if (!Utility.isEmpty(acceptedList)){
			    	sortedList.addAll(acceptedList);
			    	acceptedLists = (ArrayList)this.createVirtualRecordForRecurring(sessionContainer,conn,acceptedList,startDate,endDate,navMode,"R");
			    }
			    if (!Utility.isEmpty(acceptedLists)) {
			    	sortedList.addAll(acceptedLists);
			    }
		    }
	    } else if (selectedUserID != sessionContainer.getUserRecordID().intValue()){
		    ArrayList acceptedList = (ArrayList)calendarRecordDAO.getInviteCalendarListByUserID(
		    		sessionContainer.getUserRecordID(),
		    		new Integer(selectedUserID),
		    		startDate,
		    		endDate,
						new String[] {
								CalendarRecord.EVENT_TYPE_CALENDAR_MEETING},
						"Y");
		    ArrayList acceptedLists = null;
		    if (!Utility.isEmpty(acceptedList)){
		    	sortedList.addAll(acceptedList);
		    	acceptedLists = (ArrayList)this.createVirtualRecordForRecurring(sessionContainer,conn,acceptedList,startDate,endDate,navMode,"R");
		    }
		    if (!Utility.isEmpty(acceptedLists)) {
		    	sortedList.addAll(acceptedLists);
		    }
	    }
	  	
	  	//add unaccepted invitation meeting
	    if (selectedUserID == sessionContainer.getUserRecordID().intValue()
	        || selectedUserID == -1) {
		    if (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT)){
			    ArrayList unacceptedList = (ArrayList)calendarRecordDAO.getInviteCalendarListByUserID(
			    		sessionContainer.getUserRecordID(),
			    		new Integer(-1),
			    		startDate,
			    		endDate,
							new String[] {
									CalendarRecord.EVENT_TYPE_CALENDAR_MEETING},
							"N");
			    ArrayList unacceptedLists = null;
			    if (!Utility.isEmpty(unacceptedList)){
			    	sortedList.addAll(unacceptedList);
			    	unacceptedLists = (ArrayList)this.createVirtualRecordForRecurring(sessionContainer,conn,unacceptedList,startDate,endDate,navMode,"R");
			    }
			    if (!Utility.isEmpty(unacceptedLists)){
			    	sortedList.addAll(unacceptedLists);
			    }
		    }
	    }
	  	
	  	//add self's recur meeting
			if ((selectedUserID == sessionContainer.getUserRecordID().intValue())
					|| (selectedUserID == -1)) {
		    if (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT) || selectedUserID == sessionContainer.getUserRecordID().intValue()){
					if ((!navMode.equals(CalendarRecord.NAV_MODE_LIST_TODO))
							&& (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT))) {
	          ArrayList recurCalendarList = (ArrayList) calendarRecordDAO
	          .getRecurListByDatePeriodAndStatus(sessionContainer
	              .getUserRecordID(), null, null,
								new String[] {
									CalendarRecord.EVENT_TYPE_CALENDAR_MEETING,
									CalendarRecord.EVENT_TYPE_CALENDAR_EVENT }, null, null, null);
	          ArrayList recurCalendarLists = new ArrayList();
						if (recurCalendarList.size() > 0) {
							recurCalendarLists = (ArrayList) this
									.createVirtualRecordForRecurring(
											sessionContainer, conn,
											recurCalendarList, startDate, endDate,
											navMode, "R");
							sortedList.addAll(recurCalendarLists);
						}
					}
		    }
			}
	    

    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {

      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
	  return sortedList;
  }

  /**
 	 * this function is to get the eventmeetingList contains accepted invited meetings
 	 * @param form                              Action form for struts
 	 * @param selectedUserID                    int
 	 * @param selectedGroupID										int
 	 * @param startDate                         Timestamp
 	 * @param endDate                           Timestamp
 	 * @param staffID														Integer
 	 * @param navMode														String
 	 * @return eventList                        ArrayList
 	 */
	public ArrayList getNewEventMeetingList(
			AbstractSearchForm form, 
			int selectedUserID,
			int selectedGroupID, 
			Timestamp startDate, 
			Timestamp endDate,
			String navMode) {
		ArrayList newEventList = new ArrayList();
		CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(
				sessionContainer, conn);
		
		try {
			newEventList = (ArrayList)calendarRecordDAO.getEventMeetingListByViewSearch(
					form,
					sessionContainer.getUserRecordID(),
					new Integer(selectedUserID),
					new Integer(selectedGroupID),
					null,
					startDate,
					endDate,
					new String[] {
							CalendarRecord.EVENT_TYPE_CALENDAR_EVENT,
							CalendarRecord.EVENT_TYPE_CALENDAR_MEETING });
		} catch (ApplicationException e) {
      log.error(e, e);
		}
		
		return newEventList;
	}
	
  /**
	  * funciton getNerwToDoList is getting newToDoList.
	  * @param form                            ActionForm for stuts
	  * @param request                         HttpServletRequest
	  * @param navMode                         the path of return
	  * @param selectedUserID
	  * @return newToDoList                    return a List newToDoList
	  * @throws ApplicationException           Throws Exception if cannot get the list data from DAO object
	  */
	public ArrayList getNewToDoList (
			AbstractSearchForm form,
      HttpServletRequest request, 
      String navMode)throws ApplicationException {
	   ArrayList toDoList = new ArrayList();
	   ArrayList newToDoList = new ArrayList();
	   
	   try {
	     CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(
	         sessionContainer, conn);
       if (navMode.equals(CalendarRecord.NAV_MODE_LIST_TODO)) {
      	 toDoList = (ArrayList)calendarRecordDAO.getNewToDoList(
      			 form,
      			 sessionContainer.getUserRecordID(),
      			 null,
      			 null,
   					 new String[] {
   							CalendarRecord.EVENT_TYPE_CALENDAR_TODO},
      			 null,
      			 navMode);
       }else{
      	 toDoList = (ArrayList)calendarRecordDAO.getNewToDoList(
      			 form,
      			 sessionContainer.getUserRecordID(),
      			 null,
      			 null,
   					 new String[] {
   							CalendarRecord.EVENT_TYPE_CALENDAR_TODO},
   					 GlobalConstant.FALSE,
   					 navMode);
       }

	   } catch (ApplicationException appEx) {
	     throw appEx;
	   } catch (Exception e) {

	     throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
	   }
	   
	   if (!Utility.isEmpty(toDoList)) {
	     //Collections.sort(toDoList, new TimeComparator());
	     Set uniqueSet = new HashSet();
	     for (int i = 0; i < toDoList.size(); i++) {
	       CalendarRecord calendar = (CalendarRecord) toDoList.get(i);
	       if (uniqueSet.add( calendar.getID())) {
	         newToDoList.add(toDoList.get(i));
	       }
	     }
	   }
	   
	   return newToDoList;
	}
  
  
  /**
   * this function is to get the selectedGroupID.
   * @param request
   * @return
   */
  public int getSelectedGroupID(HttpServletRequest request) {
    HttpSession session=request.getSession();
    int selectedGroupID = -1;
    if (!Utility.isEmpty(session.getAttribute("CALENDAR_SELECTED_GROUPID"))){
      selectedGroupID = ((Integer)session.getAttribute("CALENDAR_SELECTED_GROUPID")).intValue();      
    }
    session.setAttribute("CALENDAR_SELECTED_GROUPID", new Integer(selectedGroupID));
    return selectedGroupID;
  }

  /**
   *
   * @param sessionContainer                  the Container of session item
   * @param conn                              getConnection
   * @param recurList                         List
   * @param startDate
   * @param endDate
   * @param navMode
   * @return recurTypeAList or recurTypeBList
   * @throws ApplicationException             Throws Exception if cannot get the list data from DAO object
   */
  public List createVirtualRecordForRecurring(SessionContainer
                                               sessionContainer,
                                               Connection conn,
                                               ArrayList recurList,
                                               Timestamp startDate,
                                               Timestamp endDate,
                                               String navMode,String recordType)
      throws ApplicationException {
    List newList = new ArrayList();
    List recurTypeAList = new ArrayList();
    List recurTypeBList = new ArrayList();
    List recurRTypeAList = new ArrayList();
    List recurRTypeBList = new ArrayList();    
    CalendarRecord tempCalendarRecord = null;  
    CalendarRecurDAObject calendarRecurDAO = new CalendarRecurDAObject(
        sessionContainer, conn);
    int repeatRange = 0;
    for (int i = 0; i < recurList.size(); i++) {
      recurTypeAList.clear();     
      CalendarRecord calendar = (CalendarRecord) recurList.get(i);      
      CalendarRecur calendarRecur = (CalendarRecur) calendarRecurDAO.
          getObjectByCalendarID(calendar.getID());
      if(Utility.isEmpty(calendarRecur)){
      	newList.add(calendar);
        continue;
      }
      if(startDate != null && calendarRecur.getEndDate() != null && calendar.getEndtime() != null && calendar.getDatetime() != null){
    	  Timestamp timeTemp = new Timestamp(calendarRecur.getEndDate().getTime() + calendar.getEndtime().getTime() - calendar.getDatetime().getTime());
    	  timeTemp.setHours(0);
    	  timeTemp.setMinutes(0);
    	  timeTemp.setSeconds(0);
    	  timeTemp.setNanos(0);
	      if(!timeTemp.after(startDate)) {
          continue;
        }
      }
       Calendar selectedDate = Calendar.getInstance();
       if(!Utility.isEmpty(startDate)){
         selectedDate.setTime(startDate);
       }          
          if (CalendarRecord.NAV_MODE_LIST_BY_DAY.equals(navMode)) {
            repeatRange = 1;
          } else if (CalendarRecord.NAV_MODE_LIST_BY_WEEK.equals(navMode)) {
            repeatRange = 7;
          } else if (CalendarRecord.NAV_MODE_LIST_BY_MONTH.equals(navMode)) {
            repeatRange = selectedDate.getMaximum(Calendar.DATE);
          }          
          switch (calendarRecur.getRecurType().charAt(0)) {
            case 'A':  
              recurTypeAList = this.getRecordOnRecurTypeA(sessionContainer, conn,
                  calendar, calendarRecur, startDate, endDate, repeatRange);
              break;
            case 'B':  
              recurTypeBList = this.getRecordOnRecurTypeB(sessionContainer, conn,
                  calendar, calendarRecur, startDate, endDate, repeatRange);
              break;              
          }
          if (recurTypeAList.size() > 0){
              for(int j = 0 ;j < recurTypeAList.size();j++){
                if(((CalendarRecord)recurTypeAList.get(j)).getDatetime().getTime() > calendarRecur.getStartDate().getTime()){
                  tempCalendarRecord =  (CalendarRecord)recurTypeAList.get(j);
                  if("I".equals(recordType)) {
                    tempCalendarRecord.setIsInvitation(true);
                  }
                  	tempCalendarRecord.setIsAcceptance(true);
                  recurRTypeAList.add(tempCalendarRecord);
                }
                    
              }
          }          
          if (recurTypeBList.size() > 0){
              for(int j = 0 ;j < recurTypeBList.size();j++){
                if(((CalendarRecord)recurTypeBList.get(j)).getDatetime().getTime() > calendarRecur.getStartDate().getTime()){
                    tempCalendarRecord =  (CalendarRecord)recurTypeBList.get(j);
                  if("I".equals(recordType)) {
                    tempCalendarRecord.setIsInvitation(true);
                  }
                  	//tempCalendarRecord.setIsAcceptance(true);
                  recurRTypeBList.add(tempCalendarRecord);
                }
                    
              }
          }      
          if (recurTypeAList.size() > 0) {
            newList.addAll(recurRTypeAList);
          }
          if (recurTypeBList.size() > 0) {
            newList.addAll(recurRTypeBList);
//      }    
          }
    }
    return newList;
  }

  /**
   * function getRecordOnRecurTypeA return recurTypeAList.
   * @param sessionContainer                 sessionContainer
   * @param conn                             getConnection
   * @param calendar                         CalendarRecord
   * @param calendarRecur                    CalendarRecur
   * @param curStartDate                     Timestamp
   * @param curEndDate                       Timestamp
   * @param repeatRange                      Int
   * @return  virtualList                    ArrayList
   * @throws ApplicationException            Throws Exception if cannot get the list data from DAO object
   */
  private List getRecordOnRecurTypeA(SessionContainer sessionContainer,
                                     Connection conn, CalendarRecord calendar,
                                     CalendarRecur calendarRecur,
                                     Timestamp curStartDate,
                                     Timestamp curEndDate, int repeatRange)
      throws ApplicationException {
    List virtualList = new ArrayList();
    //Get the actual calendar start/end time for hour/min handling in virtual calendar record

    switch (calendarRecur.getRepeatType().charAt(0)) {
      case 'D': {
        virtualList = this.getRepeatByType(calendar, calendarRecur, curStartDate,
                                          curEndDate, repeatRange, Calendar.DAY_OF_WEEK);
      }
      break;
      case 'W': {
        virtualList = this.getRepeatByType(calendar, calendarRecur, curStartDate,
                                          curEndDate, repeatRange, Calendar.WEEK_OF_YEAR);
      }
      break;
      case 'M': {
        virtualList = this.getRepeatByType(calendar, calendarRecur, curStartDate,
                                          curEndDate, repeatRange, Calendar.MONTH);
      }
      break;
      case 'Y': {
        virtualList = this.getRepeatByType(calendar, calendarRecur, curStartDate,
                                          curEndDate, repeatRange, Calendar.YEAR);
      }
      break;
    }
    return virtualList;
  }

  /**
   * function getRecordOnRecurTypeB return recurTypeBList
   * @param sessionContainer                 sessionContainer
   * @param conn                             getConnection
   * @param calendar                         CalendarRecord
   * @param calendarRecur                    CalendarRecur
   * @param curStartDate                     Timestamp
   * @param curEndDate                       Timestamp
   * @param repeatRange                      int
   * @return virtualList
   * @throws ApplicationException            Throws Exception if cannot get the list data from DAO object
   */
  private List getRecordOnRecurTypeB(SessionContainer sessionContainer,
                                     Connection conn, CalendarRecord calendar,
                                     CalendarRecur calendarRecur,
                                     Timestamp curStartDate,
                                     Timestamp curEndDate, int repeatRange)
      throws ApplicationException {
    List virtualList = new ArrayList();
    //Get the actual calendar start/end time for hour/min handling in virtual calendar record
		Timestamp start = (Timestamp)calendar.getDatetime().clone();
    Timestamp end = (Timestamp)calendar.getEndtime().clone();
    if (!Utility.isEmpty(end)) {
      GregorianCalendar greCal1 = new GregorianCalendar(start.getYear(),start.getMonth(),start.getDate());
      GregorianCalendar greCal2 = new GregorianCalendar(end.getYear(),end.getMonth(),end.getDate());
      int i = 0;
      int j = 0;
      for (;greCal1.get(GregorianCalendar.YEAR)!=greCal2.get(GregorianCalendar.YEAR) || greCal1.get(GregorianCalendar.MONTH)!=greCal2.get(GregorianCalendar.MONTH) || greCal1.get(GregorianCalendar.DATE)!=greCal2.get(GregorianCalendar.DATE);){
        greCal1.add(GregorianCalendar.DATE,1);
        i++;
      }
      Date curStart = calendarRecur.getStartDate();
      start.setYear(curStart.getYear());
      start.setMonth(curStart.getMonth());
      start.setDate(curStart.getDate());
      greCal1.set(start.getYear(),start.getMonth(),start.getDate());
      for (;j<i;j++){
        greCal1.add(GregorianCalendar.DATE,1);
      }
      end.setYear(greCal1.get(GregorianCalendar.YEAR));
      end.setMonth(greCal1.get(GregorianCalendar.MONTH));
      end.setDate(greCal1.get(GregorianCalendar.DATE));
    } else {
      Date curStart = calendarRecur.getStartDate();
      start.setYear(curStart.getYear());
      start.setMonth(curStart.getMonth());
      start.setDate(curStart.getDate());
    }
    
    Calendar calStart = Calendar.getInstance();
    calStart.setTime(start);
    Calendar calEnd = Calendar.getInstance();
    if(!Utility.isEmpty(end)){
      calEnd.setTime(end);
    }
    Timestamp recStartDate = calendarRecur.getStartDate(); //set the virtual start date as the calendar recur start date
    Timestamp recEndDate;
    if (Utility.isEmpty(calendarRecur.getEndDate())) {
      recEndDate = curEndDate; //set the virtual end date as the calendar current end date for 'NoEndDate' handling
    } else {
      recEndDate = calendarRecur.getEndDate(); //set the virtual end date as the calendar recur end date
    }
    Calendar tmpDate = Calendar.getInstance();
    tmpDate.setTime(recEndDate);
    tmpDate.set(Calendar.HOUR, 23);
    tmpDate.set(Calendar.MINUTE, 59);
    recEndDate = new Timestamp(tmpDate.getTimeInMillis());

    Calendar newStartDate = Calendar.getInstance();
    newStartDate.setTime(curStartDate);
    newStartDate.set(Calendar.HOUR, calStart.get(Calendar.HOUR));
    newStartDate.set(Calendar.AM_PM, calStart.get(Calendar.AM_PM));
    newStartDate.set(Calendar.MINUTE, calStart.get(Calendar.MINUTE));
    newStartDate.set(Calendar.SECOND, 0);
    newStartDate.set(Calendar.MILLISECOND, 0);

    newStartDate.add(Calendar.DATE, 1);

    Calendar newEndDate = Calendar.getInstance();
    newEndDate.setTime(curEndDate);
    //occur type B
    int repeatOn = calendarRecur.getOccurType().intValue();
    int repeatOnMonth = calendarRecur.getOccurMonth().intValue();

    Timestamp tmpStart = new Timestamp(newStartDate.getTimeInMillis());
    Timestamp tmpEnd = new Timestamp(newEndDate.getTimeInMillis());
    Calendar calTmpStart = Calendar.getInstance();
    calTmpStart.setTime(recStartDate);
    if ( (recStartDate.before(tmpStart) && recEndDate.after(tmpStart)) ||
        repeatRange == 31 || repeatRange == 7 || repeatRange == 1 || repeatRange == 0) {
      int loopRange = 31; //basic one month loop, to get the range of week number
      Calendar nextDate = Calendar.getInstance();
      if (repeatRange != 31) {
        nextDate.setTime(newStartDate.getTime());
        nextDate.add(Calendar.DATE, 1);
        newStartDate.set(Calendar.DATE, 1);
        loopRange = 62; //for daily and weekly view, need to get week number correctly using 2 month range
        //check for the week that over 2 month
        if ( (newStartDate.get(Calendar.MONTH) < newEndDate.get(Calendar.MONTH)) &&
            (calTmpStart.get(Calendar.DATE) <= newEndDate.get(Calendar.DATE))) {
          newStartDate.add(Calendar.MONTH, 1);
          loopRange = 31;
        }
        if ( (newStartDate.get(Calendar.MONTH) == newEndDate.get(Calendar.MONTH))) {
          loopRange = 31;
        }
      }
      //month listing
      List weeklyCalendar = new ArrayList();
      for (int i = 0; i <= loopRange; i++) {
        nextDate.setTime(newStartDate.getTime());
        nextDate.add(Calendar.DATE, 6);
        if (newStartDate.get(Calendar.DAY_OF_WEEK) ==
            calendarRecur.getOccurWeekDay().intValue()) {
          Calendar recStartCalendar = Calendar.getInstance();
          recStartCalendar.setTime(recStartDate);
          int reminderDiff = 1;
          if (recStartCalendar.get(Calendar.DATE) < 7) {
            if (newStartDate.get(Calendar.MONTH) == nextDate.get(Calendar.MONTH)) {
              reminderDiff = (newStartDate.get(Calendar.MONTH) -
                              recStartCalendar.get(Calendar.MONTH)) %
                  calendarRecur.getOccurMonth().intValue();
            } else {
              reminderDiff = ( (newStartDate.get(Calendar.MONTH) + 1) -
                              recStartCalendar.get(Calendar.MONTH)) %
                  calendarRecur.getOccurMonth().intValue();
            }
          } else {
            reminderDiff = (newStartDate.get(Calendar.MONTH) -
                            recStartCalendar.get(Calendar.MONTH)) %
                calendarRecur.getOccurMonth().intValue();
          }
          if (reminderDiff == 0) {
            Calendar cal = (Calendar) ( newStartDate).clone();
            weeklyCalendar.add(cal);
          } else {
            weeklyCalendar.add(null);
          }
        }
        newStartDate.add(Calendar.DATE, 1);
        newEndDate.add(Calendar.DATE, 1);
      }
      for (int i = 0; i < weeklyCalendar.size(); i++) {
        if (!Utility.isEmpty(weeklyCalendar.get(i))) {
          Calendar startCal = (Calendar) weeklyCalendar.get(i);
          if (calendarRecur.getOccurType().intValue() == (i + 1)) {
            CalendarRecord virCalendar = (CalendarRecord) ( calendar).clone();
            Calendar date = (Calendar) ( startCal).clone();
            virCalendar.setDatetime(new Timestamp(date.getTimeInMillis()));
            if(!Utility.isEmpty(end)){
              virCalendar.setEndtime(new Timestamp(date.getTimeInMillis() +
                  (end.getTime() - start.getTime())));
            }						
            if (!Utility.isEmpty(calendarRecur.getEndDate())){
							if (!((virCalendar.getDatetime().before(calendarRecur.getStartDate()) && virCalendar.getEndtime().before(calendarRecur.getStartDate())) || (virCalendar.getDatetime().after(calendarRecur.getEndDate()) && virCalendar.getEndtime().after(calendarRecur.getEndDate())))){
								virtualList.add(virCalendar);
							}
						} else {
							if (!(virCalendar.getDatetime().before(calendarRecur.getStartDate()) && virCalendar.getEndtime().before(calendarRecur.getStartDate()))){
								virtualList.add(virCalendar);
							}
						}
          }
        }
      }
      if (calendarRecur.getOccurType().intValue() == 9) {
        for (int i = weeklyCalendar.size() - 1; i >= 0; i--) {
          //whereas the Fifth week always will be the lastest week
          Calendar startCal = (Calendar) weeklyCalendar.get(i);
          if (!Utility.isEmpty(startCal)) {
	          for (;(startCal.get(GregorianCalendar.MONTH)!=curStartDate.getMonth());){
	            startCal.add(GregorianCalendar.DATE,-7);
	          }
	          
            CalendarRecord virCalendar = (CalendarRecord) ( calendar).clone();
            Calendar date = (Calendar) ( startCal).clone();
            virCalendar.setDatetime(new Timestamp(date.getTimeInMillis()));
            if(!Utility.isEmpty(end)){
              virCalendar.setEndtime(new Timestamp(date.getTimeInMillis() +
                                                 (end.getTime() - start.getTime())));
            }
						if (!Utility.isEmpty(calendarRecur.getEndDate())){
							if (!((virCalendar.getDatetime().before(calendarRecur.getStartDate()) && virCalendar.getEndtime().before(calendarRecur.getStartDate())) || (virCalendar.getDatetime().after(calendarRecur.getEndDate()) && virCalendar.getEndtime().after(calendarRecur.getEndDate())))){
								virtualList.add(virCalendar);
							}
						} else {
							if (!(virCalendar.getDatetime().before(calendarRecur.getStartDate()) && virCalendar.getEndtime().before(calendarRecur.getStartDate()))){
								virtualList.add(virCalendar);
							}
						}
            break;
          }
        }
      }
    }
    return virtualList;
  }

  private List getRepeatByType(CalendarRecord calendar,
      CalendarRecur calendarRecur,
      Timestamp curStartDate, Timestamp curEndDate,
      int repeatRange, int type) {
    List virtualList = new ArrayList();
		Timestamp start = (Timestamp)calendar.getDatetime().clone();
		Timestamp end = (Timestamp)calendar.getEndtime().clone();
    if (!Utility.isEmpty(end)) {
      GregorianCalendar greCal1 = new GregorianCalendar(start.getYear(),start.getMonth(),start.getDate());
      GregorianCalendar greCal2 = new GregorianCalendar(end.getYear(),end.getMonth(),end.getDate());
      int i = 0;
      int j = 0;
      for (;greCal1.get(GregorianCalendar.YEAR)!=greCal2.get(GregorianCalendar.YEAR) || greCal1.get(GregorianCalendar.MONTH)!=greCal2.get(GregorianCalendar.MONTH) || greCal1.get(GregorianCalendar.DATE)!=greCal2.get(GregorianCalendar.DATE);){
        greCal1.add(GregorianCalendar.DATE,1);
        i++;
      }
      Date curStart = calendarRecur.getStartDate();
      start.setYear(curStart.getYear());
      start.setMonth(curStart.getMonth());
      start.setDate(curStart.getDate());
      greCal1.set(start.getYear(),start.getMonth(),start.getDate());
      for (;j<i;j++){
        greCal1.add(GregorianCalendar.DATE,1);
      }
      end.setYear(greCal1.get(GregorianCalendar.YEAR));
      end.setMonth(greCal1.get(GregorianCalendar.MONTH));
      end.setDate(greCal1.get(GregorianCalendar.DATE));
    } else {
      Date curStart = calendarRecur.getStartDate();
      start.setYear(curStart.getYear());
      start.setMonth(curStart.getMonth());
      start.setDate(curStart.getDate());
    }
		
    Calendar calStart = Calendar.getInstance();
    calStart.setTime(start);
    Calendar calEnd = Calendar.getInstance();
    if(!Utility.isEmpty(end)){
      calEnd.setTime(end);
    }
    
    Calendar tempCal = (Calendar)calStart.clone();
    Timestamp recStartDate = calendarRecur.getStartDate();
    Timestamp recEndDate;
    if (Utility.isEmpty(calendarRecur.getEndDate())) {
      //set the virtual end date as the calendar current end date for 'NoEndDate' handling
      recEndDate = curEndDate;
    } else {
      //set the virtual end date as the calendar recur end date
      recEndDate = calendarRecur.getEndDate();
    }
    Calendar selectCalStart = Calendar.getInstance();
    selectCalStart.setTime(recStartDate);
    Calendar selectCalEnd = Calendar.getInstance();
    selectCalEnd.setTime(recEndDate);
    while(tempCal.before(selectCalEnd)){
        int repeatOn = calendarRecur.getRepeatOn().intValue();
        
        if(tempCal.after(selectCalStart)){
            CalendarRecord virCalendar = (CalendarRecord) ( calendar).clone();
            virCalendar.setDatetime(new Timestamp(tempCal.getTimeInMillis()));
        if(!Utility.isEmpty(end)){
          virCalendar.setEndtime(new Timestamp(tempCal.getTimeInMillis() +
                                             (end.getTime() - start.getTime())));
        }
				if (!Utility.isEmpty(calendarRecur.getEndDate())){
					if (!((virCalendar.getDatetime().before(calendarRecur.getStartDate()) && virCalendar.getEndtime().before(calendarRecur.getStartDate())) || (virCalendar.getDatetime().after(calendarRecur.getEndDate()) && virCalendar.getEndtime().after(calendarRecur.getEndDate())))){
						virtualList.add(virCalendar);
					}
				} else {
					if (!(virCalendar.getDatetime().before(calendarRecur.getStartDate()) && virCalendar.getEndtime().before(calendarRecur.getStartDate()))){
						virtualList.add(virCalendar);
					}
				}
      }
      tempCal.add(type,repeatOn);
    }
    return virtualList;
  }

  /**
   * this function is to get calendarList.
   * @param sessionContainer            SessionContainer
   * @param conn                        Connection
   * @param form                        AbstractSearchForm
   * @param startDate                   Timestamp
   * @param endDate                     Timestamp
   * @param selectedUserID              int
   * @return calendarList
   */
  private ArrayList getCalenarList(SessionContainer sessionContainer,
                                   Connection conn, AbstractSearchForm form,
                                   Timestamp startDate, Timestamp endDate,
                                   int selectedUserID) {
    ArrayList calendarList = new ArrayList();
    CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(
        sessionContainer, conn);
    try {
      if ( selectedUserID ==
            sessionContainer.getUserRecordID().intValue()) {
        calendarList = (ArrayList) calendarRecordDAO.
            getListByDatePeriodAndEventTypeAndCalendarIDs(form,
            sessionContainer.getUserRecordID(), startDate,
            endDate, new String[] {CalendarRecord.EVENT_TYPE_CALENDAR_MEETING,
            CalendarRecord.EVENT_TYPE_CALENDAR_EVENT,
            CalendarRecord.EVENT_TYPE_CALENDAR_TODO}
            , null, null);
      }
 			else if (selectedUserID == -1) {
     	  calendarList = (ArrayList) calendarRecordDAO
 		.getListByDatePeriodAndEventTypeAndCalendarIDs(
 				form,
 				sessionContainer.getUserRecordID(),
 				startDate,
 				endDate,
 				new String[] {
 						CalendarRecord.EVENT_TYPE_CALENDAR_MEETING,
 						CalendarRecord.EVENT_TYPE_CALENDAR_EVENT,
 						CalendarRecord.EVENT_TYPE_CALENDAR_TODO },
 				null, null);
   }
    } catch (ApplicationException e) {}
    return calendarList;
  }

  /**
   * getEventList
   * @param sortedList
   * @return eventList
   */
  public ArrayList getEventList(ArrayList sortedList) {
    ArrayList eventList = new ArrayList();
    //Collections.sort(sortedList, new TimeComparator());
    Set uniqueSet = new HashSet();

    for (int i = 0; i < sortedList.size(); i++) {
      if (sortedList.get(i)instanceof CalendarRecord) {
        CalendarRecord calendar = (CalendarRecord) sortedList.get(i);
        if ((!CalendarRecord.EVENT_TYPE_CALENDAR_TODO.equals(calendar.
            getEventType()))
            && calendar.getIsInvitation() 
            &&(uniqueSet.add( "C_" + calendar.getID().toString() +
               calendar.getDatetime().getTime()))) {
          eventList.add(calendar);
        }
      }
    }

    return eventList;

  }
  
 	/**
 	 * getEventList
 	 * @param sortedList
 	 * @return eventList
 	 */
 	public ArrayList getEventListNew(ArrayList sortedList) {
 		ArrayList eventList = new ArrayList();
 		//Collections.sort(sortedList, new TimeComparator());
 		Set uniqueSet = new HashSet();

 		for (int i = 0; i < sortedList.size(); i++) {
 			if (sortedList.get(i) instanceof CalendarRecord) {
 				CalendarRecord calendar = (CalendarRecord) sortedList.get(i);
 				if ((!CalendarRecord.EVENT_TYPE_CALENDAR_TODO.equals(calendar
 						.getEventType()))
 						&& (uniqueSet.add("C_"
 								+ calendar.getID().toString()
 								+ calendar.getDatetime().getTime()))) {
 					eventList.add(calendar);
 				}
 			}
 		}
 		return eventList;
 	}

  /**
   * this function is to get selectedUserIDList.
   * @param sessionContainer
   * @param conn
   * @param recipientType
   * @param userRecords
   * @param recipientRecords
   * @param userRoles
   * @param userGroups
   * @return selectedUserIDList
   */
  public List getSelectUserIDList(SessionContainer sessionContainer,
                                  Connection conn, 
                                  String[] userRecords,
                                  String[] userRoles,
                                  String[] userGroups) {
    List selectedUserIDList = new ArrayList();
    List tmpList = new ArrayList();
    List tmpSelectedUserList = new ArrayList();
    MtmUserRecordUserGroupDAObject userGroupDAO = new
        MtmUserRecordUserGroupDAObject(sessionContainer, conn);
    MtmUserRecordUserRoleDAObject userRoleDAO = new
        MtmUserRecordUserRoleDAObject(sessionContainer, conn);

    try {
        if (!Utility.isEmpty(userRecords)) {
          for (int i = 0; i < userRecords.length; i++) {
         	 if (!Utility.isEmpty(userRecords[i])){
         		 selectedUserIDList.add(new Integer(userRecords[i]));
         	 }
          } 
        }
        if (!Utility.isEmpty(userGroups)) {         
          for (int i = 0; i < userGroups.length; i++) {
         	 if (!Utility.isEmpty(userGroups[i])){
         		 tmpList.add(new Integer(userGroups[i]));
         	 }
          }       
          tmpSelectedUserList = userGroupDAO.getUserIDListByUserGroupIDList(tmpList);
          if (!Utility.isEmpty(tmpSelectedUserList)){
             for (int ii = 0; ii< tmpSelectedUserList.size(); ii++){
               if (selectedUserIDList.indexOf(tmpSelectedUserList.get(ii))==-1){
                 selectedUserIDList.add(tmpSelectedUserList.get(ii)); 
               }
             }
          }       
        }
        if (!Utility.isEmpty(userRoles)) {
          tmpList = new ArrayList();
          for (int i = 0; i < userRoles.length; i++) {
         	 if (!Utility.isEmpty(userRoles[i])){
         		 tmpList.add(new Integer(userRoles[i]));
         	 }
          }
          tmpSelectedUserList = userRoleDAO.getUserIDListByUserRoleList(tmpList);
          if (!Utility.isEmpty(tmpSelectedUserList)){
           for (int ii = 0; ii< tmpSelectedUserList.size(); ii++){
             if (selectedUserIDList.indexOf(tmpSelectedUserList.get(ii))==-1){
               selectedUserIDList.add(tmpSelectedUserList.get(ii)); 
             }
           }
         }       
        }

    } catch (ApplicationException e) {}
    return selectedUserIDList;
  }

	/**
	 *
	 * @param sessionContainer                  the Container of session item
	 * @param conn                              getConnection
	 * @param recurList                         List
	 * @param startDate
	 * @param endDate
	 * @param navMode
	 * @return recurTypeAList or recurTypeBList
	 * @throws ApplicationException             Throws Exception if cannot get the list data from DAO object
	 */
	public List createVirtualRecordForRecurringForForm(
			SessionContainer sessionContainer, Connection conn,
			AbstractActionForm form, Timestamp startDate, Timestamp endDate,
			String navMode, String recordType) throws ApplicationException {
		List newList = new ArrayList();
		List recurTypeAList = new ArrayList();
		List recurTypeBList = new ArrayList();
		List recurRTypeAList = new ArrayList();
		List recurRTypeBList = new ArrayList();
  	MaintCalendarRecordForm tmpForm = (MaintCalendarRecordForm)form;
		CalendarRecord tempCalendarRecord = null;
		//CalendarRecurDAObject calendarRecurDAO = new CalendarRecurDAObject(
		//		sessionContainer, conn);
		int repeatRange = 0;
		//for (int i = 0; i < recurList.size(); i++) {
		recurTypeAList.clear();
		//CalendarRecord calendar = (CalendarRecord) recurList.get(i);
    CalendarRecord calendar = (CalendarRecord)tmpForm.getFormData();
    
    newList.add(calendar);
    
    CalendarRecur calendarRecur = null;
    if (!Utility.isEmpty(calendar.getIsRecurrence()) && calendar.getIsRecurrence().equals("Y")){
    	calendarRecur = new CalendarRecur();
	    calendarRecur.setCalendarID(calendar.getID());
	    calendarRecur.setStartDate(calendar.getRecurStartDate());
	    calendarRecur.setEndDate(calendar.getRecurEndDate());
	    calendarRecur.setRepeatTimes(calendar.getRepeatTimes());
	    calendarRecur.setRecurType(calendar.getRecurType());
	    calendarRecur.setRepeatOn(calendar.getRepeatOn());
	    calendarRecur.setRepeatType(calendar.getRepeatType());
	    calendarRecur.setRepeatTypeDay(calendar.getRepeatTypeDay());
	    calendarRecur.setOccurType(calendar.getOccurType());
	    calendarRecur.setOccurWeekDay(calendar.getOccurWeekDay());
	    calendarRecur.setOccurMonth(calendar.getOccurMonth());
	    calendarRecur.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    }
		if (Utility.isEmpty(calendarRecur)){
			return newList;
		}
     if(startDate != null && calendarRecur.getEndDate() != null && calendar.getEndtime() != null && calendar.getDatetime() != null){
   	  Timestamp timeTemp = new Timestamp(calendarRecur.getEndDate().getTime() + calendar.getEndtime().getTime() - calendar.getDatetime().getTime());
   	  timeTemp.setHours(0);
   	  timeTemp.setMinutes(0);
   	  timeTemp.setSeconds(0);
   	  timeTemp.setNanos(0);
      if(!timeTemp.after(startDate)){
      	return newList;
      }
		 }
			Calendar selectedDate = Calendar.getInstance();
			if (!Utility.isEmpty(startDate)) {
				selectedDate.setTime(startDate);
			}
			if (CalendarRecord.NAV_MODE_LIST_BY_DAY.equals(navMode)) {
        repeatRange = 1;
      } else if (CalendarRecord.NAV_MODE_LIST_BY_WEEK.equals(navMode)) {
        repeatRange = 7;
      } else if (CalendarRecord.NAV_MODE_LIST_BY_MONTH.equals(navMode)) {
        repeatRange = selectedDate.getMaximum(Calendar.DATE);
      }
			switch (calendarRecur.getRecurType().charAt(0)) {
			case 'A':
				recurTypeAList = this.getRecordOnRecurTypeA(sessionContainer,
						conn, calendar, calendarRecur, startDate, endDate,
						repeatRange);
				break;
			case 'B':
				recurTypeBList = this.getRecordOnRecurTypeB(sessionContainer,
						conn, calendar, calendarRecur, startDate, endDate,
						repeatRange);
				break;
			}
			if (recurTypeAList.size() > 0) {
				for (int j = 0; j < recurTypeAList.size(); j++) {
					if (((CalendarRecord) recurTypeAList.get(j)).getDatetime()
							.getTime() > calendarRecur.getStartDate().getTime()) {
						tempCalendarRecord = (CalendarRecord) recurTypeAList
								.get(j);
						if ("I".equals(recordType)) {
              tempCalendarRecord.setIsInvitation(true);
            }
						recurRTypeAList.add(tempCalendarRecord);
					}

				}
			}
			if (recurTypeBList.size() > 0) {
				for (int j = 0; j < recurTypeBList.size(); j++) {
					if (((CalendarRecord) recurTypeBList.get(j)).getDatetime()
							.getTime() > calendarRecur.getStartDate().getTime()) {
						tempCalendarRecord = (CalendarRecord) recurTypeBList
								.get(j);
						if ("I".equals(recordType)) {
              tempCalendarRecord.setIsInvitation(true);
            }
						recurRTypeBList.add(tempCalendarRecord);
					}

				}
			}
			if (recurTypeAList.size() > 0) {
        newList.addAll(recurRTypeAList);
      }
			if (recurTypeBList.size() > 0) {
        newList.addAll(recurRTypeBList);
      }
			return newList;
	}
  
	public List getMailAddresses(Connection conn, SessionContainer sessionContainer, CalendarRecord calendarRecord, HttpServletRequest request){
		AlertManager alertManager = new AlertManager(sessionContainer, conn);
    String[] userRecords = null;
    String[] userRoles = null;
    String[] userGroups = null;

    userRecords = request.getParameterValues("userRecords");
    userRoles = request.getParameterValues("userRoles");
    userGroups = request.getParameterValues("userGroups");        
    //get the notifyUserIDList
    List notifyUserIDList = null;
    try {
    	notifyUserIDList = alertManager.getDistinctUserIDListByLists(
			    userRecords, userGroups, userRoles);
			notifyUserIDList.remove(calendarRecord.getCreatorID());
			
		} catch (ApplicationException e) {
			
      log.error(e, e);
		}
    
		return notifyUserIDList;
	}
	
	public StringBuffer mailContent(Connection conn, SessionContainer sessionContainer,Integer objectID, String userName, Timestamp refDate, Integer createrId, String type){
		return new NotificationAdapter(sessionContainer, conn).emailForCalendarInviteContent(objectID, userName, refDate, createrId, type);
	}

	public void sendInvitationEmail(Connection conn, SessionContainer sessionContainer,CalendarRecord calendarRecord, HttpServletRequest request, String type) throws ApplicationException {

    EmailDeliveryMessage msg = new EmailDeliveryMessage();    
    String curUserEmail = UserInfoFactory.getUserEmailAddress(sessionContainer.getUserRecordID());
    if (Utility.isEmpty(curUserEmail)) {
      curUserEmail = SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_ADMIN_ADDRESS);
    }
    String curUserName = UserInfoFactory.getUserFullName(sessionContainer.getUserRecordID());
    if (Utility.isEmpty(curUserName)) {
      curUserName = SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_ADMIN_NAME);
    }
    
    //  recipients.
    //msg.addToRecipient();
    msg.setCharset(SystemParameterFactory.getSystemParameter(SystemParameterConstant.ENCODING));
    try {
    	List notifyUserIDList = this.getMailAddresses(conn, sessionContainer, calendarRecord, request);
      for (int i = 0; i < notifyUserIDList.size(); i++) {
        //int notifyUserID = ( (Integer)notifyUserIDList.get(i)).intValue();

        
        Integer userID = (Integer)notifyUserIDList.get(i);
        String userName = UserInfoFactory.getUserFullName(userID);
        String userEmail = UserInfoFactory.getUserEmailAddress(userID);
        Integer objectId = calendarRecord.getID();
        Integer createrId = calendarRecord.getCreatorID();
        String content = this.mailContent(conn, sessionContainer, objectId, userName, calendarRecord.getDatetime(), createrId, type).toString();
			  msg.setSender(new GenericAddress(curUserEmail, curUserName,"utf-8"));
		    //msg.addToRecipient(new GenericAddress("jicle.wang@dcivision.com"));
		    msg.addToRecipient(new GenericAddress(userEmail, userName, "UTF-8"));
			  msg.setSubject(SystemParameterFactory.getSystemParameter(SystemParameterConstant.CALENDAR_MAIL_SUBJECT));
			
	      msg.setMailContent(content);
        NotificationWay emailNotification = NotificationWayFactory.getNotificationInstance(NotificationWay.EMAIL_NOTIFICATION_INSTANCE);
        emailNotification.addDeliveryMessage( msg);
        emailNotification.send();
      }
    } catch (UnsupportedEncodingException uee) {
      log.error(uee.getMessage(), uee);
      throw new ApplicationException(uee);
    }  
  }
	
  /**
   * function is to get navMode.
   * @param request                      HttpServletRequest
   * @return navMode                     path of return
   */
  public String getNavMode(SessionContainer sessionContainer, Connection conn,
                           HttpServletRequest request) {
    //org hard coded navMoed of Calendar Listing Options
    String navMode = null;
    Integer defStartShowHour = null;
    Integer defEndShowHour = null;
    Integer defaultGroup = null;
    Integer selectedGroupID = null;
    HttpSession session = request.getSession();

    //get user defined navMode from perference
    try {
      CalendarPerferenceDAObject calPerferenceDAO = new
          CalendarPerferenceDAObject(sessionContainer, conn);
      CalendarPerference calendarPerference = (CalendarPerference)
          calPerferenceDAO.getByObjectByUserRecordID(sessionContainer.
          getUserRecordID());

      if (!Utility.isEmpty(calendarPerference)) {
        navMode = calendarPerference.getDefaultView();
        defStartShowHour = calendarPerference.getStartShowHour();
        defEndShowHour = calendarPerference.getEndShowHour();
        defaultGroup = Utility.isEmpty(calendarPerference.getDefaultGroup())?new Integer(-1):calendarPerference.getDefaultGroup();
        session.setAttribute("defStartShowHour", defStartShowHour);
        session.setAttribute("defEndShowHour", defEndShowHour);
        session.setAttribute("defaultGroup", defaultGroup);
        request.setAttribute("defNavMode", navMode);
      } else {
        navMode = SystemParameterFactory.getSystemParameter(
            SystemParameterConstant.CALENDAR_DEFAULT_NAV_MODE);
      }
    } catch (ApplicationException e) {

    }
    if (!Utility.isEmpty(request.getParameter("selectedGroupID"))){
      selectedGroupID = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedGroupID")));
      session.setAttribute("CALENDAR_SELECTED_GROUPID", selectedGroupID);
    } else if(Utility.isEmpty(session.getAttribute("CALENDAR_SELECTED_GROUPID"))){
      session.setAttribute("CALENDAR_SELECTED_GROUPID", defaultGroup);
    }
    if (!Utility.isEmpty(request.getAttribute("CALENDAR_SELECTED_NAV_MODE"))) {
      navMode = (String) request.getAttribute("CALENDAR_SELECTED_NAV_MODE");
    }

    if (!Utility.isEmpty(request.getParameter("navMode"))) {
      navMode = request.getParameter("navMode").trim();
      request.setAttribute("CALENDAR_SELECTED_NAV_MODE", navMode);
    }
    return navMode;
  }
  
  /**
   * this function is to get the selectedDate.
   * @param request
   * @return selectedDate
   */
  public Calendar getSelectDate(HttpServletRequest request) {
    Calendar selectedDate = Calendar.getInstance();    
    HttpSession session = request.getSession();
    if (!Utility.isEmpty(request.getAttribute("CALENDAR_SELECTED_DATE"))) {
      selectedDate = (Calendar) request.getAttribute("CALENDAR_SELECTED_DATE");
    }

    if (!Utility.isEmpty(request.getParameter("selectedDay") ) &&
        !Utility.isEmpty(request.getParameter("selectedMonth")) &&
        !Utility.isEmpty(request.getParameter("selectedYear"))) {

      int tempDay = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedDay"))).intValue();
      int tempMonth = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedMonth"))).intValue();
      int tempYear = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedYear"))).intValue();     
      selectedDate.set(tempYear, tempMonth-1, 1);
      int tempDay1=selectedDate.getActualMaximum(Calendar.DATE);
      if(tempDay1<tempDay){
    	  tempDay=tempDay1;
      }      
      selectedDate.set(tempYear, tempMonth-1, tempDay);
      session.setAttribute("CALENDAR_SELECTED_DATE", selectedDate);
    }
    return selectedDate;
  }
  
  /**
   * this function is to get the navigate navMode.
   * @param request
   * @return navMode
   */
  public String getListNavMode(HttpServletRequest request) {
    String navMode = null;
    if (!Utility.isEmpty(request.getAttribute("defNavMode"))) {
      navMode = (String) request.getAttribute("defNavMode");
    } else {
      navMode = SystemParameterFactory.getSystemParameter(
          SystemParameterConstant.CALENDAR_DEFAULT_NAV_MODE);
    }

    if (!Utility.isEmpty(request.getAttribute("CALENDAR_SELECTED_NAV_MODE"))) {
      navMode = (String) request.getAttribute("CALENDAR_SELECTED_NAV_MODE");
    }

    request.setAttribute("CALENDAR_SELECTED_NAV_MODE", navMode);

    return navMode;
  }

  /**
   * this function is to get the startDate and endDate of ListDate.
   * @param request
   * @param navMode
   * @return dateList
   */
  public ArrayList getListStartEndDate(HttpServletRequest request,
                                       String navMode) {
    ArrayList dateList = new ArrayList();
    
    Calendar selectedDateInSession = null;
    GregorianCalendar gCal = new GregorianCalendar();
    Timestamp startDate = null;
    Timestamp endDate = null;
    int selectedDay = gCal.get(GregorianCalendar.DAY_OF_MONTH);
    int selectedMonth = gCal.get(GregorianCalendar.MONTH) + 1;
    int selectedYear = gCal.get(GregorianCalendar.YEAR);
   if (!Utility.isEmpty(request.getSession().getAttribute("CALENDAR_SELECTED_DATE"))) {
      selectedDateInSession = (Calendar)request.getSession().getAttribute(
          "CALENDAR_SELECTED_DATE");
      selectedDay = selectedDateInSession.get(Calendar.DAY_OF_MONTH);
      selectedMonth = selectedDateInSession.get(Calendar.MONTH) + 1 ;
      selectedYear = selectedDateInSession.get(Calendar.YEAR);
    }
    if (!Utility.isEmpty(request.getParameter("selectedDay"))) {
      selectedDay = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedDay"))).intValue();
    }
    if (!Utility.isEmpty(request.getParameter("selectedMonth"))) {
      selectedMonth = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedMonth"))).intValue();
    }
    if (!Utility.isEmpty(request.getParameter("selectedYear"))) {
      selectedYear = (TextUtility.parseIntegerObj(request.getParameter(
          "selectedYear"))).intValue();
    }
    if (!navMode.equals(CalendarRecord.NAV_MODE_LIST_EVENT)) {
      if (navMode.equals(CalendarRecord.NAV_MODE_LIST_BY_DAY)) {
        Calendar selectedDate = Calendar.getInstance();
				selectedDate.set(selectedYear, selectedMonth -1 , selectedDay,
						00, 00, 00);
				selectedDate.set(Calendar.MILLISECOND, 000);
        startDate = new Timestamp(selectedDate.getTimeInMillis());
        selectedDate.add(Calendar.DATE, 1);
        endDate = new Timestamp(selectedDate.getTimeInMillis());
      } else if (navMode.equals(CalendarRecord.NAV_MODE_LIST_BY_WEEK)) {
        Calendar selectedDate = Calendar.getInstance();
        Calendar currentDayofWeek = Calendar.getInstance();        
        if (request.getParameter("listName")!=null){
        	if(!Utility.isEmpty(request.getSession().getAttribute("selectedMonth"))&&!Utility.isEmpty(request.getSession().getAttribute("selectedYear"))
        			&&!Utility.isEmpty(request.getSession().getAttribute("selectedDay"))){
        		selectedMonth = ((Integer)request.getSession().getAttribute("selectedMonth")).intValue();
        		selectedYear=((Integer)request.getSession().getAttribute("selectedYear")).intValue();            
        		selectedDay=((Integer)request.getSession().getAttribute("selectedDay")).intValue();
        	}else{
        		selectedDate.set(selectedYear,selectedMonth-1,selectedDay);
        		Utility.setCalendarTime(selectedDate,0,0,0,0);

        		// 	This fragment of code handle the case if the selectedDate is larger than
        		//	what it supposed to be,like '32'.
        		selectedDay = selectedDate.get(Calendar.DAY_OF_MONTH);
        		selectedMonth = selectedDate.get(Calendar.MONTH)+1;
        		selectedYear = selectedDate.get(Calendar.YEAR);				
        	}		
        }
				/*
				 * Update Code Start
				 * Author		Jim.Zhou
				 * Date			2006/05/30
				 * Bug			#5293
				 */
        selectedDate.set(selectedYear, selectedMonth - 1, selectedDay, 00, 00,00);
				/*
				 * Update Code End
				 */
				selectedDate.set(Calendar.MILLISECOND, 0);
        currentDayofWeek.setTime(selectedDate.getTime());
        int dayofWeek=currentDayofWeek.get(Calendar.DAY_OF_WEEK);
        currentDayofWeek.add(Calendar.DAY_OF_WEEK,1-dayofWeek);
        selectedDate.add(Calendar.DAY_OF_WEEK,1-dayofWeek);
        selectedDate.set(Calendar.MILLISECOND, 0);

        //selectedDate.add(Calendar.DATE, -1);
        startDate = new Timestamp(selectedDate.getTimeInMillis());

        selectedDate.add(Calendar.DATE, 7);
        endDate = new Timestamp(selectedDate.getTimeInMillis());

      } else if (navMode.equals(CalendarRecord.NAV_MODE_LIST_BY_MONTH)) {
        Calendar selectedDate = Calendar.getInstance();
        selectedDate.set(selectedYear, selectedMonth - 1, 1, 0, 0, 0);
        selectedDate.set(Calendar.MILLISECOND, 0);
        startDate = new Timestamp(selectedDate.getTimeInMillis());
				selectedDate.add(Calendar.MONTH, 1);
        endDate = new Timestamp(selectedDate.getTimeInMillis());
      } else {
        Calendar selectedDate = Calendar.getInstance();
        selectedDate.set(selectedYear, selectedMonth - 1, selectedDay, 23, 59,
                         59);
        selectedDate.set(Calendar.MILLISECOND, 999);
        selectedDate.add(Calendar.DATE, -1);
        startDate = new Timestamp(selectedDate.getTimeInMillis());
        selectedDate.add(Calendar.DATE, 1);
        endDate = new Timestamp(selectedDate.getTimeInMillis());
      }

    }
    dateList.add(startDate);
    dateList.add(endDate);
    return dateList;
  }
  
  /**
   * this function is to get selectedUserID.
   * @param sessionContainer
   * @param request
   * @return selectedID
   */
  public int getSelectedUserID(SessionContainer sessionContainer,
      HttpServletRequest request) {
    int selectedUserID = -1;
    HttpSession session=request.getSession();
    if(!Utility.isEmpty(session.getAttribute("CALENDAR_SELECTED_GROUPID"))){
      int selectedGroupID = ((Integer)session.getAttribute("CALENDAR_SELECTED_GROUPID")).intValue();
      if(selectedGroupID==-1){
      selectedUserID = sessionContainer.getUserRecordID().intValue();
      }      
    }
    if (!Utility.isEmpty(session.getAttribute("CALENDAR_SELECTED_USERID"))) {
      selectedUserID = ( (Integer) session.getAttribute("CALENDAR_SELECTED_USERID")).intValue();
    }    
    if (!Utility.isEmpty(request.getParameter("selectedUserID"))) {
      selectedUserID = (TextUtility.parseIntegerObj(request.getParameter(
      "selectedUserID"))).intValue();
    }
    session.setAttribute("CALENDAR_SELECTED_USERID", new Integer(selectedUserID));
    return selectedUserID;
  }

  /**
   * function getUserList is getting the userList.
   * @param request                           HttpServletRequest
   * @param selectedGroupID
   * @return userList
   * @throws ApplicationException             Throws Exception if cannot get the list data from DAO object
   */
  public ArrayList getUserList(SessionContainer sessionContainer, Connection conn,
                          HttpServletRequest request, int selectedGroupID)
      throws ApplicationException {
    ArrayList userList = null;
    try {
      UserRecordDAObject userRecordDAO = new UserRecordDAObject(
          sessionContainer, conn);
      if (selectedGroupID > 0) {
        userList = (ArrayList) userRecordDAO.getUserRecordFullNameByUserGroupID(new
            Integer(selectedGroupID),
            sessionContainer.getUserRecordID(),
            GlobalConstant.STATUS_ACTIVE);
      } else {
        userList = (ArrayList) userRecordDAO.getAllOtherUserFullNameByStatus(
            GlobalConstant.STATUS_ACTIVE,
            sessionContainer.getUserRecordID());
      }
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {

      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }

    return userList;
  }

  /**
   * function getNewSortedList is getting the newSortedList.
   * @param sortedList
   * @return newSortedList
   */
  public ArrayList getNewSortedList(ArrayList sortedList) {
    ArrayList newSortedList = new ArrayList();
    //Collections.sort(sortedList, new TimeComparator());
    HashMap tempMap = new HashMap();
    StringBuffer strBuffer = new StringBuffer();
    for (int i = 0; i < sortedList.size(); i++){
      if (sortedList.get(i) instanceof CalendarRecord ) {
        CalendarRecord calendar = (CalendarRecord) sortedList.get(i);
        if(!CalendarRecord.EVENT_TYPE_CALENDAR_TODO.equals(calendar
            .getEventType())){
          strBuffer.append("C_")
                   .append(calendar.getID().toString())
                   .append(calendar.getDatetime().getTime());
          if(!tempMap.containsKey(strBuffer.toString())){
            tempMap.put(strBuffer.toString(), calendar);
          }else{
            CalendarRecord tempCal = (CalendarRecord)tempMap.get(strBuffer.toString());
            if(!tempCal.getIsInvitation()&& calendar.getIsInvitation()){
              tempMap.remove(strBuffer.toString());
              tempMap.put(strBuffer.toString(), calendar);
            }
          }
          strBuffer = new StringBuffer();
        }
      }
    }
    Iterator key = tempMap.keySet().iterator();
    while(key.hasNext()){
    	newSortedList.add(tempMap.get(key.next()));
    }
    
    //sort
    //Add By Jim.Zhou		2006/08/24	Bug EIP-111
    ArrayList result = new ArrayList();
  	Map sortTMap = new TreeMap();
  	for(int i = 0 ; i < newSortedList.size();i++){
  		CalendarRecord tmpRecord = (CalendarRecord)newSortedList.get(i);
  		if (!Utility.isEmpty(tmpRecord)){
  			sortTMap.put(tmpRecord.getDatetime().toString()+tmpRecord.getID(),tmpRecord);
  		}
  	}
  	result.addAll(sortTMap.values());
    //Add End
  	
    return result;
  }

  /**
   * this function is to get the startDate and endDate and selectedDate.
   * @param request                        HttpServletRequest
   * @return dateList                      startDate and endDate and selectedDate
   */
  public ArrayList getRecStartEndDate(HttpServletRequest request) {
    ArrayList dateList = new ArrayList();
    Timestamp startDate = null;
    Timestamp endDate = null;
    Calendar selectedDateInSession = null;
    GregorianCalendar gCal = new GregorianCalendar();
    int selectedDay = gCal.get(GregorianCalendar.DAY_OF_MONTH);
    int selectedMonth = gCal.get(GregorianCalendar.MONTH) + 1;
    int selectedYear = gCal.get(GregorianCalendar.YEAR);

    if (!Utility.isEmpty(request.getAttribute("CALENDAR_SELECTED_DATE"))) {
      selectedDateInSession = (Calendar) request.getAttribute(
          "CALENDAR_SELECTED_DATE");
      selectedDay = selectedDateInSession.get(Calendar.DAY_OF_MONTH);
      selectedMonth = selectedDateInSession.get(Calendar.MONTH);
      selectedYear = selectedDateInSession.get(Calendar.YEAR);
    }

    if (!Utility.isEmpty(request.getParameter("startDate"))) {

      String targetDate = request.getParameter("startDate");

      selectedMonth = new Integer(targetDate.substring(5, 7)).intValue();
      selectedDay = new Integer(targetDate.substring(8, 10)).intValue();
      selectedYear = new Integer(targetDate.substring(0, 4)).intValue();

      request.setAttribute("startDate", targetDate);
      HttpSession session = request.getSession();
      session.setAttribute("startDate", targetDate);
    } else {

      if (!Utility.isEmpty(request.getParameter("selectedDay"))) {
        selectedDay = (TextUtility.parseIntegerObj(request.getParameter(
            "selectedDay"))).intValue();
      }
      if (!Utility.isEmpty(request.getParameter("selectedMonth"))) {
        selectedMonth = (TextUtility.parseIntegerObj(request.getParameter(
            "selectedMonth"))).intValue();
      }
      if (!Utility.isEmpty(request.getParameter("selectedYear"))) {
        selectedYear = (TextUtility.parseIntegerObj(request.getParameter(
            "selectedYear"))).intValue();
      }
    }

    Calendar selectedDate = Calendar.getInstance();
    selectedDate.set(selectedYear, selectedMonth - 1, selectedDay, 23, 59, 59);
    selectedDate.set(Calendar.MILLISECOND, 999);
    selectedDate.add(Calendar.DATE, -1);
    startDate = new Timestamp(selectedDate.getTimeInMillis());
    selectedDate.add(Calendar.DATE, 1);
    endDate = new Timestamp(selectedDate.getTimeInMillis());

    dateList.add(selectedDate);
    dateList.add(startDate);
    dateList.add(endDate);
    return dateList;
  }
  
	/**
	 * this function is get the selectedUserCalendarMap;
	 * @param sessionContainer                     SessionContainer
	 * @param conn                                 Connection
	 * @param request															 HttpServletRequest
	 * @param form                                 ActionForm for struts
	 * @param selectedUserIDList                   selectedUserIDList
	 * @param startDate
	 * @param endDate
	 * @param appendedQuery
	 * @return selectedUserCalendarMap
	 * @throws ApplicationException 
	 */
	public Map getSelectUserCalendarMap(SessionContainer sessionContainer,
			Connection conn,HttpServletRequest request, AbstractSearchForm form, List selectedUserIDList,
			Timestamp startDate, Timestamp endDate, String appendedQuery) throws ApplicationException {
		Map selectedUserCalendarMap = new HashMap();
		List selectedUserCalendarList = new ArrayList();
		for (int i = 0; i < selectedUserIDList.size(); i++) {
	   
			selectedUserCalendarList = getSortedList(
					form,
					request, 
					CalendarRecord.NAV_MODE_LIST_EVENT, 
					((Integer) selectedUserIDList.get(i)).intValue(),
	        (Integer) selectedUserIDList.get(i), 
	        startDate, 
	        endDate);
			selectedUserCalendarMap.put(selectedUserIDList.get(i),
					this.getNewSortedList((ArrayList)selectedUserCalendarList));
		}
		return selectedUserCalendarMap;
	}
}
